home *** CD-ROM | disk | FTP | other *** search
/ Otherware / Otherware_1_SB_Development.iso / mac / developm / source / ncsat.cpt / Telnet2.5 final / tcpip / util.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-04-05  |  26.5 KB  |  1,199 lines

  1.  
  2. /*#define NEW_STUFF 1     /* BYU - changed to "MacTCPdriver" in make file. */
  3.  
  4.  
  5. /*
  6. *   Util.c
  7. *   utility library for use with the Network kernel
  8. *
  9. *   version 2, full session layer, TK started 6/17/87
  10. *
  11. ****************************************************************************
  12. *                                                                          *
  13. *      part of:                                                            *
  14. *      Network kernel for NCSA Telnet                                      *
  15. *      by Tim Krauskopf                                                    *
  16. *                                                                          *
  17. *      National Center for Supercomputing Applications                     *
  18. *      152 Computing Applications Building                                 *
  19. *      605 E. Springfield Ave.                                             *
  20. *      Champaign, IL  61820                                                *
  21. *                                                                          *
  22. *    Copyright (c) 1987, Board of Trustees of the University of Illinois   *
  23. *                                                                          *
  24. ****************************************************************************
  25. */
  26. #include <OSUtils.h>
  27. #include <stdio.h>
  28. /*#include "whatami.h"            /* BYU 2.4.16 MPW - access via protocol.h */
  29. #include "protocol.h"            /* BYU 2.4.16 MPW - for netusend() */
  30. #include "hostform.h"
  31. #include "confile.h"
  32. #include "ethertalk.h"            /* BYU 2.4.16 MPW - for netconfig() */
  33. #include "ether.h"                /* BYU 2.4.16 MPW - for netconfig() */
  34. #include "ip.h"                    /* BYU 2.4.16 MPW - for netusend() */
  35. #include "mactools.h"            /* BYU 2.4.15 MPW - for netarpme() */
  36. #include "userd.h"
  37. #include "user.h"                /* BYU 2.4.16 MPW - for netxopen() */
  38. #include "tools.h"
  39. #include "bkgr.h"
  40. #include <MacTCPCommonTypes.h>
  41. #include <AddressXlation.h>
  42.  
  43.  
  44.  
  45. #ifdef MAC
  46. #include <String.h>
  47. #include <Memory.h>
  48. #include "macutil.h"
  49. #endif
  50.  
  51. #ifdef PC
  52. #include <string.h>
  53. #else
  54. #ifdef AZTEC
  55. #define strchr(A,B) index(A,B)
  56. #endif
  57. #endif
  58.  
  59. extern void putln(),userftpd();    /* BYU */
  60. char                             /* special function types */
  61.             *neterrstring();
  62. int32 time();                    /* don't forget this sucker! */
  63.  
  64. extern struct machinfo *Sns;
  65.  
  66. static unsigned char
  67.             *Ssstemps[] = {
  68.             "capfile",
  69.             "hp.out",
  70.             "ps.out",
  71.             "tek.out"
  72.             };
  73.  
  74. char Sptypes[NPORTS];        /* port types assigned for session use */
  75.  
  76. extern short slip_connection;    /* BYU 2.4.15 */
  77.  
  78. extern int EtherNet;            /* BYU 2.4.15 */
  79.  
  80. extern struct config Scon;        /* hardware configuration */
  81.  
  82. #define NTIMES 30
  83.  
  84. /*
  85. *  timer queue of events which will be placed into the event queue
  86. *  when the time is up.
  87. */
  88. struct {
  89.     unsigned char
  90.         eclass,                    /* event queue data */
  91.         event;
  92.     int
  93.         next,                    /* next item in list */
  94.         idata;
  95.     int32 when;                /* when timer is to go off */
  96. } Stq[NTIMES];
  97.  
  98.  
  99. struct DNRstruct {
  100.         struct machinfo *m;
  101.         Boolean done;
  102.         };
  103.  
  104. static int
  105.         domwait = 0,            /* is domain waiting for nameserver? */
  106.         Stfirst,Stfree;            /* pointers for timer queue */
  107.  
  108. #define PFTP 1
  109. #define PRCP 2
  110. #define PDATA 3
  111. #define PDOMAIN 4
  112.  
  113. /**************************************************************************/
  114. /*  Stask
  115. *   A higher level version of netsleep
  116. *
  117. *   This manages the timer queue
  118. */
  119.  
  120. static int32 recent=0L;
  121.  
  122. void Stask
  123.   (
  124.     void
  125.   )
  126.     {
  127.     long t;
  128.     int i;
  129.  
  130. /*#ifndef APPLE_DRIVERS        /* BYU 2.4.16 */
  131.     netsleep(0);
  132. /*#endif APPLE_DRIVERS        /* BYU 2.4.16 */
  133.  
  134. /*
  135. *  Check the timer queue to see if something should be posted
  136. *  First check for timer wraparound
  137. */
  138.     t = time(NULL);
  139. #ifdef PC
  140.     if (t < recent) {
  141.         i = Stfirst;
  142.         while (i >= 0) {
  143.             Stq[i].when -= WRAPTIME;
  144.             i = Stq[i].next;
  145.         }
  146.     }
  147. #endif
  148.     recent = t;                            /* save most recent time */
  149.  
  150.     while (Stfirst >= 0 && t > Stq[Stfirst].when) {        
  151.                                 /* Q is not empty and timer is going off */
  152.         i = Stfirst;
  153.         netputevent(Stq[i].eclass,Stq[i].event,Stq[i].idata);
  154.         Stfirst = Stq[Stfirst].next;    /* remove from q */
  155.         Stq[i].next = Stfree;
  156.         Stfree = i;                        /* add to free list */
  157.     }
  158.  
  159.  
  160. }
  161.  
  162. /************************************************************************/
  163. /*  Snetinit
  164. *   Do network initialization for those who want the defaults all
  165. *   set for them.  Recommend that neterrchange be called before
  166. *   initializing network stuff.
  167. */
  168. int Snetinit
  169.   (
  170.     void
  171.   )
  172.     {
  173.     int i;
  174.  
  175. /*
  176. *  set up the file names
  177. */
  178.     Scon.capture = Ssstemps[0];
  179.     Scon.hpfile = Ssstemps[1];
  180.     Scon.psfile = Ssstemps[2];
  181.     Scon.tekfile = Ssstemps[3];
  182.  
  183.     neteventinit();                /* initializes for error messages to count */
  184.  
  185.     for (i=0; i<NPORTS; i++)
  186.         Sptypes[i] = -1;            /* clear port type flags */
  187.  
  188.     for (i=0; i<NTIMES; i++)
  189.         Stq[i].next = i+1;            /* load linked list */
  190.     Stq[NTIMES-1].next = -1;        /* anchor end */
  191.     Stfirst = -1;
  192.     Stfree = 0;
  193.  
  194.     if (!Sreadhosts()) {             /* parses config file */
  195. #ifdef PC
  196.         netparms(Scon.irqnum,Scon.address,Scon.ioaddr);
  197. #endif
  198.         netconfig(Scon.hw);
  199.  
  200.         if (!netinit()) {            /* starts up hardware */
  201. /*
  202. *  Check for the need to RARP and do it
  203. */
  204.             netgetip(Scon.myipnum);    /* get stored ip num */
  205.             if (comparen(Scon.myipnum,"RARP",4)) {    /* need RARP */
  206.                 if (netgetrarp())    /* stores in nnipnum at lower layer */
  207.                     return(-2);
  208.                 netgetip(Scon.myipnum);
  209.                 netsetip(Scon.myipnum);    
  210.             }
  211.  
  212. /*
  213. *  Give the lower layers a chance to check to see if anyone else
  214. *  is using the same ip number.  Usually generates an ARP packet.
  215. */
  216.             netarpme(Scon.myipnum);        
  217.  
  218.             Ssetgates();        /* BYU serial - moved to maclook.c, finishes IP inits */
  219.             Stask();
  220.             return(0);
  221.         }
  222.     }
  223.  
  224.     return(-1);    
  225. } /* Snetinit */
  226.  
  227. /**************************************************************************/
  228. /*  Stimerset
  229. *  Sets an asynchronous timer which is checked in Stask()
  230. *  usage:
  231. *  Time is in seconds
  232. *  Stimerset(class,event,dat,time)
  233. *    int class,event,dat,time;
  234. *    class,event,dat is the event which should be posted at the specified
  235. *    time.  Accuracy is dependent on how often Stask is called.
  236. */
  237.  
  238. int Stimerset
  239.   (
  240.     int class,
  241.     int event,
  242.     int dat,
  243.     int howlong
  244.   )
  245.     {
  246.     int i,j,jlast,retval;
  247.     int32 gooff;
  248.  
  249.     retval = 0;
  250.     gooff = time(NULL) + howlong;
  251.  
  252.     if (Stfree < 0) {                /* queue is full, post first event */
  253.         Stfree = Stfirst;
  254.         Stfirst = Stq[Stfirst].next;
  255.         Stq[Stfree].next = -1;
  256.         netputevent(Stq[Stfree].eclass,Stq[Stfree].event,Stq[Stfree].idata);
  257.         retval = -1;
  258.     }
  259.  
  260.     Stq[Stfree].idata = dat;                /* event to occur at that time */
  261.     Stq[Stfree].event = event;
  262.     Stq[Stfree].eclass = class;
  263.     Stq[Stfree].when = gooff;
  264.     i = Stfree;                            /* remove from free list */
  265.     Stfree = Stq[i].next;
  266.  
  267.     if (Stfirst < 0) {                    /* if no queue yet */
  268.         Stfirst = i;
  269.         Stq[i].next = -1;                /* anchor active q */
  270.     }
  271.  
  272.     else if (gooff < Stq[Stfirst].when) {    /* goes first on list */
  273.         Stq[i].next = Stfirst;                /* at beginning of list */
  274.         Stfirst = i;
  275.     }
  276.  
  277.     else {                                    /* goes in middle */
  278.  
  279.         j = jlast = Stfirst;                /* search q from beginning */
  280.  
  281.         while (gooff >= Stq[j].when && j >= 0) {
  282.             jlast = j;
  283.             j = Stq[j].next;
  284.         }
  285.         Stq[i].next = j;                    /* insert in q */
  286.         Stq[jlast].next = i;
  287.     }
  288.  
  289.     return(retval);
  290. }
  291.  
  292. /**************************************************************************/
  293. /*  Snetopen
  294. *
  295. *   Takes a pointer to a machine record, looked up with Sgethost and
  296. *   initiates the TCP open call.
  297. *
  298. */
  299. int Snetopen
  300.   (
  301.     struct machinfo *m,
  302.     int tport,                /* BYU 2.4.15 */
  303.     short connectionType    /* BYU 2.4.15 */
  304.   )
  305.     {
  306.     int j;
  307.  
  308.     if ((connectionType == 0) && (EtherNet == -100)) {        /* BYU 2.4.15 */
  309.         OtherError((char *) "\pError opening network port.",(char *) "\pNetwork was not initialized.");        /* BYU 2.4.15 */
  310.         return -1;                                            /* BYU 2.4.15 */
  311.     }                                                        /* BYU 2.4.15 */
  312.  
  313.     if (!connectionType && (!m || m->mstat < HAVEIP))        /* BYU 2.4.15 */
  314.         return(-1);
  315.  
  316. #if 1                                /* BYU 2.4.15 */
  317.     j = netxopen((uint8 *) m->hostip,tport,m->retrans,m->mtu,m->maxseg,m->window,connectionType);    /* BYU 2.4.15 */
  318. #else                                /* BYU 2.4.15 */
  319.     j = netxopen((uint32 *) m->hostip,tport,m->retrans,m->mtu,m->maxseg,m->window);
  320.                                     /* do the open call */
  321. #endif                                /* BYU 2.4.15 */
  322.  
  323.     if (j >= 0) {
  324.         Sptypes[j] = -1;            /* is allocated to user */
  325.         if ((connectionType == 0) || slip_connection) {                /* BYU 2.4.15 */
  326.             Stimerset(CONCLASS,CONFAIL,j,m->conto);                    /* BYU 2.4.15 */
  327.             Stimerset(SCLASS,RETRYCON,j,m->retrans/TICKSPERSEC+2);    /* BYU 2.4.15 */
  328.         }                                                            /* BYU 2.4.15 */
  329.     }
  330.  
  331.     return(j);
  332. }
  333.  
  334.  
  335. /**************************************************************************/
  336. /*
  337. *  special domain data structures
  338. */
  339. #define DOMSIZE 512                /* maximum domain message size to mess with */
  340.  
  341. /*
  342. *  Header for the DOMAIN queries
  343. *  ALL OF THESE ARE BYTE SWAPPED QUANTITIES!
  344. *  We are the poor slobs who are incompatible with the world's byte order
  345. */
  346. struct dhead {
  347. uint16
  348.     ident,                /* unique identifier */
  349.     flags,    
  350.     qdcount,            /* question section, # of entries */
  351.     ancount,            /* answers, how many */
  352.     nscount,            /* count of name server RRs */
  353.     arcount;            /* number of "additional" records */
  354. };
  355.  
  356. /*
  357. *  flag masks for the flags field of the DOMAIN header
  358. */
  359. #define DQR        0x8000            /* query = 0, response = 1 */
  360. #define DOPCODE    0x7100            /* opcode, see below */
  361. #define DAA        0x0400            /* Authoritative answer */
  362. #define DTC        0x0200            /* Truncation, response was cut off at 512 */
  363. #define DRD        0x0100            /* Recursion desired */
  364. #define DRA        0x0080            /* Recursion available */
  365. #define DRCODE    0x000F            /* response code, see below */
  366.  
  367.                                 /* opcode possible values: */
  368. #define DOPQUERY    0            /* a standard query */
  369. #define DOPIQ        1            /* an inverse query */
  370. #define DOPCQM        2            /* a completion query, multiple reply */
  371. #define DOPCQU        3             /* a completion query, single reply */
  372. /* the rest reserved for future */
  373.  
  374.                                 /* legal response codes: */
  375. #define DROK    0                /* okay response */
  376. #define DRFORM    1                /* format error */
  377. #define DRFAIL    2                /* their problem, server failed */
  378. #define DRNAME    3                /* name error, we know name doesn't exist */
  379. #define DRNOPE    4                /* no can do request */
  380. #define DRNOWAY    5                /* name server refusing to do request */
  381.  
  382. #define DTYPEA    1                /* host address resource record (RR) */
  383. #define DTYPEPTR    12            /* a domain name ptr */
  384.  
  385. #define DIN        1                /* ARPA internet class */
  386. #define DWILD    255                /* wildcard for several of the classifications */
  387.  
  388. /*
  389. *  a resource record is made up of a compressed domain name followed by
  390. *  this structure.  All of these ints need to be byteswapped before use.
  391. */
  392. struct rrpart {
  393.     uint16
  394.         rtype,                    /* resource record type = DTYPEA */
  395.         rclass;                    /* RR class = DIN */
  396.     uint32
  397.         rttl;                    /* time-to-live, changed to 32 bits */
  398.     uint16
  399.         rdlength;                /* length of next field */
  400.     uint8
  401.         rdata[DOMSIZE];            /* data field */
  402. };
  403.  
  404. /*
  405. *  data for domain name lookup
  406. */
  407. struct useek {
  408.     struct dhead h;
  409.     uint8 x[DOMSIZE];
  410. } question;
  411.  
  412. qinit()
  413.     {
  414.     question.h.flags = intswap(DRD);
  415.     question.h.qdcount = intswap(1);
  416.     question.h.ancount = 0;
  417.     question.h.nscount = 0;
  418.     question.h.arcount = 0;
  419. }
  420.  
  421.  
  422. /*********************************************************************/
  423. /*  packdom
  424. *   pack a regular text string into a packed domain name, suitable
  425. *   for the name server.
  426. */
  427. packdom(dst,src)
  428.     char *src,*dst;
  429.     {
  430.     char *p,*q,*savedst;
  431.     int i,dotflag,defflag;
  432.  
  433.     p = src;
  434.     dotflag = defflag = 0;
  435.     savedst = dst;
  436.  
  437.     do {                            /* copy whole string */
  438.         *dst = 0;
  439.         q = dst + 1;
  440.  
  441. /*
  442. *  copy the next label along, char by char until it meets a period or
  443. *  end of string.
  444. */
  445.         while (*p && (*p != '.')) 
  446.             *q++ = *p++;
  447.  
  448.         i = p - src;
  449.         if (i > 0x3f)
  450.             return(-1);
  451.         *dst = i;
  452.         *q = 0;
  453.  
  454.         if (*p) {                    /* update pointers */
  455.             dotflag = 1;
  456.             src = ++p;
  457.             dst = q;
  458.         }
  459.         else if (!dotflag && !defflag && Scon.defdom) {
  460.             p = Scon.defdom;        /* continue packing with default */
  461.             defflag = 1;
  462.             src = p;
  463.             dst = q;
  464.             netposterr(801);        /* using default domain */
  465.         }
  466.  
  467.     } while (*p);
  468.  
  469.     q++;
  470.     return(q-savedst);            /* length of packed string */
  471. }
  472.  
  473. /*********************************************************************/
  474. /*  unpackdom
  475. *  Unpack a compressed domain name that we have received from another
  476. *  host.  Handles pointers to continuation domain names -- buf is used
  477. *  as the base for the offset of any pointer which is present.
  478. *  returns the number of bytes at src which should be skipped over.
  479. *  Includes the NULL terminator in its length count.
  480. */
  481. unpackdom(dst,src,buf)
  482.     char *src,*dst,buf[];
  483.     {
  484.     int i,j,retval;
  485.     char *savesrc;
  486.  
  487.     savesrc = src;
  488.     retval = 0;
  489.  
  490.     while (*src) {
  491.         j = *src;
  492.  
  493.         while ((j & 0xC0) == 0xC0) {
  494.             if (!retval)
  495.                 retval = src-savesrc+2;
  496.             src++;
  497.             src = &buf[(j & 0x3f)*256+*src];        /* pointer dereference */
  498.             j = *src;
  499.         }
  500.  
  501.         src++;
  502.         for (i=0; i < (j & 0x3f) ; i++)
  503.             *dst++ = *src++;
  504.  
  505.         *dst++ = '.';
  506.     }
  507.  
  508.     *(--dst) = 0;            /* add terminator */
  509.     src++;                    /* account for terminator on src */
  510.  
  511.     if (!retval)
  512.         retval = src-savesrc;
  513.  
  514.     return(retval);
  515. }
  516.  
  517. /*********************************************************************/
  518. /*  sendom
  519. *   put together a domain lookup packet and send it
  520. *   uses port 53
  521. */
  522. sendom(s,towho,num)
  523.     char *s,*towho;
  524.     int16 num;
  525.     {
  526.     uint16 i,ulen;
  527.     uint8 *psave,*p;
  528.  
  529.     psave = (uint8 *)question.x;
  530.  
  531.     i = packdom(question.x,s);
  532.  
  533. /*
  534. *  load the fields of the question structure a character at a time so
  535. *  that 68000 machines won't barf.
  536. */
  537.     p = &question.x[i];
  538.     *p++ = 0;                /* high byte of qtype */
  539.     *p++ = DTYPEA;            /* number is < 256, so we know high byte=0 */
  540.     *p++ = 0;                /* high byte of qclass */
  541.     *p++ = DIN;                /* qtype is < 256 */
  542.  
  543.     question.h.ident = intswap(num);
  544.     ulen = sizeof(struct dhead)+(p-psave);
  545.  
  546.     netusend(towho, 53, 997, (unsigned char *) &question, ulen);
  547.     
  548. }
  549.  
  550.  
  551. pascal void DNRDone(hostInfoPtr,DNR)
  552. struct hostInfo *hostInfoPtr;
  553. struct DNRstruct *DNR;
  554. {
  555.     DNR->m->mstat = HAVEIP; 
  556.     putln("got to DNRdone");
  557.     if (!hostInfoPtr->rtnCode)            /* no error, so open it up */
  558.     {
  559.         movebytes(DNR->m->hostip,hostInfoPtr->addr,4);
  560.         netputevent(USERCLASS,DOMOK,DNR->m->mno);
  561.     }
  562.     else
  563.         netputevent(USERCLASS,DOMFAIL,DNR->m->mno); /* cant find ip # */
  564.     DNR->done = true;
  565.     DisposPtr((char *)DNR);
  566.     DisposPtr((char *)hostInfoPtr);
  567.     putln("got past DNRdone");
  568.  
  569. }
  570.  
  571.  
  572.  
  573.  
  574. /**************************************************************************/
  575. /*  Sdomain
  576. *   DOMAIN based name lookup
  577. *   query a domain name server to get an IP number
  578. *    Returns the machine number of the machine record for future reference.
  579. *   Events generated will have this number tagged with them.
  580. *   Returns various negative numbers on error conditions.
  581. */
  582. int Sdomain
  583.   (
  584.     char *mname
  585.   )
  586. {
  587. struct machinfo    *m;
  588.  
  589. /*#ifdef MacTCPdriver                    /* BYU 2.4.16 */
  590. OSErr            theError;
  591. struct hostInfo    *myHost;
  592. Boolean            done;
  593. int                i;
  594. struct DNRstruct *DNRstuff;
  595. /*#endif                                /* BYU 2.4.16 */
  596.  
  597. /*#ifndef MacTCPdriver                    /* BYU 2.4.16 - was "#ifdef NEW_STUFF" */
  598.     if (!Sns && EtherNet != -99)         /* BYU 2.4.16 - no nameserver, give up now */
  599.         return(-1);
  600. /*#endif                                /* BYU 2.4.16 */
  601.  
  602.     while (*mname && *mname < 33)        /* kill leading spaces */
  603.         mname++;
  604.     if (!(*mname))
  605.         return(-1);
  606.  
  607.     if (!(m = Smadd(mname)))
  608.         return(-1);                        /* adds the number to the machlist */
  609.  
  610.     if (domwait < Scon.domto)
  611.         domwait = Scon.domto;            /* set the minimum timeout */
  612.     
  613. /*#ifdef MacTCPdriver                    /* BYU 2.4.16 - was NEW_STUFF */
  614.  
  615.     if (EtherNet == -99) {                /* BYU 2.4.16 */
  616.  
  617.         DNRstuff = (struct DNRstruct *) NewPtr(sizeof(struct DNRstruct));
  618.         myHost = (struct hostInfo *) NewPtr(sizeof(struct hostInfo)*2);
  619.  
  620. #if 0                                                /* BYU 2.4.16 - not needed */
  621.         putln("Going to try to get domain name");
  622.         putln("\015");                                /* BYU 2.4.18 - changed \n to \015 */
  623. #endif                                                /* BYU 2.4.16 */
  624.  
  625.         for (i = 0; i < NUM_ALT_ADDRS; i++)
  626.             myHost->addr[i] = 0;
  627.         done = false;
  628.         if (!m->hname) m->hname = m->sname;
  629.         DNRstuff->m = m;
  630.         DNRstuff->done = done;
  631.         theError = StrToAddr(m->hname,myHost,DNRDone,(Ptr)DNRstuff);
  632.     
  633.         if (theError != cacheFault) DNRDone(myHost,DNRstuff);
  634.         m->mstat = HAVEIP;
  635. /*#else                                        /* BYU 2.4.16 */
  636.  
  637.     } else {                                /* BYU 2.4.16 */
  638.  
  639.         qinit();                            /* initialize some flag fields */
  640.         netulisten(997);                    /* pick a return port */
  641.         if (!m->hname)
  642.             m->hname = m->sname;            /* copy pointer to sname */
  643.         sendom(m->hname,Sns->hostip,m->mno);    /* try UDP */
  644.         Stimerset(SCLASS,UDPTO,m->mno,domwait);    /* time out quickly first time */
  645.         m->mstat = UDPDOM;
  646. /*#endif                                    /* BYU 2.4.16 */
  647.  
  648.     }                                        /* BYU 2.4.16 */
  649.  
  650.     return(m->mno);
  651.   }
  652.  
  653. /*********************************************************************/
  654. /*  ddextract
  655. *   extract the ip number from a response message.
  656. *   returns the appropriate status code and if the ip number is available,
  657. *   copies it into mip
  658. */
  659. int ddextract
  660.   (
  661.     struct useek *qp,
  662.     unsigned char *mip
  663.   )
  664. {
  665. uint16 i,j,nans,rcode;
  666. struct rrpart *rrp;
  667. uint8 *p,space[260];
  668.  
  669.     nans = intswap(qp->h.ancount);                /* number of answers */
  670.     rcode = DRCODE & intswap(qp->h.flags);        /* return code for this message*/
  671.     if (rcode > 0)
  672.         return(rcode);
  673.  
  674.     if (nans > 0 &&                                /* at least one answer */
  675.         (intswap(qp->h.flags) & DQR)) {            /* response flag is set */
  676.         p = (uint8 *)qp->x;                    /* where question starts */
  677.         i = unpackdom(space,p,qp);                /* unpack question name */
  678. /*  spec defines name then  QTYPE + QCLASS = 4 bytes */
  679.         p += i+4;
  680. /*
  681. *  at this point, there may be several answers.  We will take the first
  682. *  one which has an IP number.  There may be other types of answers that
  683. *  we want to support later.
  684. */
  685.         while (nans-- > 0) {                    /* look at each answer */
  686.             i = unpackdom(space,p,qp);            /* answer name to unpack */
  687. /*            n_puts(space);*/
  688.             p += i;                                /* account for string */
  689.             rrp = (struct rrpart *)p;            /* resource record here */
  690. /*
  691. *  check things which might not align on 68000 chip one byte at a time
  692. */
  693.             if (!*p && *(p+1) == DTYPEA &&         /* correct type and class */
  694.                 !*(p+2) && *(p+3) == DIN) {
  695.                 movebytes(mip,rrp->rdata,4);    /* save IP #         */
  696.                 return(0);                        /* successful return */
  697.             }
  698.             movebytes(&j,&rrp->rdlength,2);        /* 68000 alignment */
  699.             p += 10+intswap(j);                    /* length of rest of RR */
  700.         }
  701.     }
  702.  
  703.     return(-1);                        /* generic failed to parse */
  704. }
  705.  
  706. /****************************************************************************/
  707. /*  Stimerunset
  708. *   Remove all such timer events from the queue
  709. *   They must match all three fields, event, class and optional data
  710. *
  711. */
  712. int Stimerunset
  713.   (
  714.     unsigned char class,
  715.     unsigned char event,
  716.     int dat
  717.   )
  718. {
  719. int i,ilast,retval;
  720.  
  721.     retval = ilast = -1;
  722.     i = Stfirst;
  723.     while (i >= 0 ) {                    /* search list */
  724.  
  725.         if (Stq[i].idata == dat &&         /* this one matches */
  726.             Stq[i].eclass == class && Stq[i].event == event) {
  727.  
  728.             retval = 0;                    /* found at least one */
  729. /*
  730. * major bug fix -- if first element matched, old code could crash
  731. */
  732.             if (i == Stfirst) {
  733.                 Stfirst = Stq[i].next;            /* first one matches */
  734.                 Stq[i].next = Stfree;            /* attach to free list */
  735.                 Stfree = i;
  736.                 i = Stfirst;
  737.                 continue;                        /* start list over */
  738.             }
  739.             else {
  740.                 Stq[ilast].next = Stq[i].next;    /* remove this entry */
  741.                 Stq[i].next = Stfree;            /* attach to free list */
  742.                 Stfree = i;
  743.                 i = ilast;
  744.             }
  745.         }
  746.  
  747.         ilast = i;
  748.         i = Stq[i].next;
  749.     }
  750.  
  751.     return(retval);
  752. }
  753.  
  754. /*********************************************************************/
  755. /*  getdomain
  756. *   Look at the results to see if our DOMAIN request is ready.
  757. *   It may be a timeout, which requires another query.
  758. */
  759.  
  760. udpdom()
  761. {
  762. struct machinfo    *m;
  763. int                i,uret,num;
  764. char            *p;
  765.  
  766.     uret = neturead((char *) &question);
  767.  
  768.     if (uret < 0)
  769.     {
  770. /*        netputevent(USERCLASS,DOMFAIL,-1);  */
  771.         return(-1);
  772.     }
  773.  
  774.     num = intswap(question.h.ident);        /* get machine number */
  775. /*
  776. *  check to see if the necessary information was in the UDP response
  777. */
  778.     m = Slooknum(num);                /* get machine info record */
  779.     if (!m)
  780.     {
  781.         netputevent(USERCLASS,DOMFAIL,num);
  782.         return(-1);
  783.     }
  784.  
  785. /*
  786. *  got a response, so reset timeout value to recommended minimum
  787. */
  788.     domwait = Scon.domto;
  789.  
  790.     i = ddextract(&question,m->hostip);
  791.  
  792.     switch (i) {
  793.         case 3:                        /* name does not exist */
  794.             netposterr(802);
  795.             p = neterrstring(-1);
  796.             strncpy(p,m->hname,78);        /* what name */
  797.             netposterr(-1);
  798.             netputevent(USERCLASS,DOMFAIL,num);
  799.             Stimerunset(SCLASS,UDPTO,num);
  800.             return(-1);
  801.         case 0:                        /* we found the IP number */
  802.             Stimerunset(SCLASS,UDPTO,num);
  803.             m->mstat = DOM;            /* mark that we have it from DOMAIN */
  804.             netputevent(USERCLASS,DOMOK,num);
  805.             return(0);
  806.         case -1:                    /* strange return code from ddextract */
  807.             netposterr(803);
  808.             break;
  809.         default:
  810.             netposterr(804);
  811.             break;
  812.     }
  813.  
  814.     return(0);
  815.  
  816. }
  817.  
  818. /**************************************************************************/
  819. /*  domto
  820. *   Handle time out for DOMAIN name lookup
  821. *   Retry as many times as recommended by config file
  822. */
  823. domto(num)
  824. int num;
  825. {
  826. struct machinfo *m;
  827.  
  828.     m = Slooknum(num);
  829.     if (!m)
  830.         return(-1);
  831.  
  832.     if (m->mstat > UDPDOM + Scon.ndom) {    /* permanent timeout */
  833.         netputevent(USERCLASS,DOMFAIL,num);
  834.         return(-1);
  835.     }
  836.     else
  837.         m->mstat++;            /* one more timeout */
  838.     
  839.     if (domwait < 20)        /* exponential backoff */
  840.         domwait <<= 1;
  841.  
  842.     Snewns();                /* rotate to next nameserver */
  843.  
  844.     qinit();
  845.  
  846.     netulisten(997);                    /* pick a return port */
  847.     sendom(m->hname,Sns->hostip,num);        /* try UDP */
  848.  
  849.     Stimerset(SCLASS,UDPTO,num,domwait);    /* time out more slowly */
  850.  
  851.     return(num);
  852.     
  853. }
  854.  
  855.  
  856. /***********************************************************************/
  857. static int son=1;
  858.  
  859. Scwritemode(mode)
  860. int mode;
  861. {
  862.     son = mode;
  863.     return(0);
  864. }
  865.  
  866. /***********************************************************************/
  867. Scmode()
  868. {
  869.     return(son);
  870. }
  871.  
  872. /***********************************************************************/
  873. static int tekon=1;
  874.  
  875. void Stekmode
  876.   (
  877.     int mode
  878.   )
  879. int mode;
  880. {
  881.         tekon = mode;
  882. }
  883.  
  884. /***********************************************************************/
  885. Stmode()
  886. {
  887.     return(tekon);
  888. }
  889.  
  890. /***********************************************************************/
  891. #ifdef PC
  892. static int rcpon=1;
  893.  
  894. Srcpmode(mode)
  895. int mode;
  896. {
  897.     rcpon = mode;
  898.     if (rcpon)
  899.         setrshd();
  900.     else
  901.         unsetrshd();
  902.     return(0);
  903. }
  904.  
  905. /***********************************************************************/
  906. Srmode()
  907. {
  908.     return(rcpon);
  909. }
  910. #endif
  911.  
  912. /***********************************************************************/
  913. static int ftpon=0;
  914.  
  915. int Sftpmode
  916.   (
  917.     int mode
  918.   )
  919. {
  920.     if (ftpon && mode)
  921.         return(-1);
  922.  
  923.     ftpon = mode;
  924.     if (ftpon)
  925.         setftp();
  926.     else
  927.         unsetftp();
  928.     return(0);
  929. }
  930.  
  931. /***********************************************************************/
  932. int Sfmode
  933.   (
  934.     void
  935.   )
  936. {
  937.     return(ftpon);
  938. }
  939.  
  940. /***********************************************************************/
  941. /*  Snewcap
  942. *   set a new capture file name
  943. */
  944. int Snewcap
  945.   (
  946.     char *s
  947.   )
  948. {
  949.     if (NULL == (Scon.capture = NewPtr(strlen(s)+1)))
  950.         return(1);
  951.     strcpy(Scon.capture,s);
  952.     return(0);
  953. }
  954.  
  955. /***********************************************************************/
  956. /*  Snewps
  957. *   set a new ps file name
  958. */
  959. int Snewpsfile
  960.   (
  961.     char *s
  962.   )
  963. {
  964.     if (NULL == (Scon.psfile = NewPtr(strlen(s)+1)))
  965.         return(1);
  966.     strcpy(Scon.psfile,s);
  967.     return(0);
  968. }
  969.  
  970. /***********************************************************************/
  971. /*  Snewhpfile
  972. *   set a new HPGL file name
  973. */
  974. int Snewhpfile
  975.   (
  976.     char *s
  977.   )
  978. {
  979.     if (NULL == (Scon.hpfile = NewPtr(strlen(s)+1)))
  980.         return(1);
  981.     strcpy(Scon.hpfile,s);
  982.     return(0);
  983. }
  984.  
  985. /***********************************************************************/
  986. /*  Snewtekfile
  987. *   set a new tek file name
  988. */
  989. int Snewtekfile
  990.   (
  991.     char *s
  992.   )
  993. {
  994.     if (NULL == (Scon.tekfile = NewPtr(strlen(s)+1)))
  995.         return(1);
  996.     strcpy(Scon.tekfile,s);
  997.     return(0);
  998. }
  999.  
  1000. /***********************************************************************/
  1001. /*  Sopencap
  1002. *   returns a file handle to an open capture file
  1003. *   Uses the locally stored capture file name.
  1004. */
  1005. FILE *
  1006. Sopencap()
  1007. {
  1008. FILE *retfp;
  1009.  
  1010.     if (NULL == (retfp = fopen(Scon.capture,"ab"))) 
  1011.         return(NULL);
  1012.  
  1013.     fseek(retfp,0L,2);        /* seek to end */
  1014.  
  1015.     return(retfp);
  1016. }
  1017.  
  1018. /****************************************************************************/
  1019. /* Scompass
  1020. *  compute and check the encrypted password
  1021. */
  1022. int Scompass
  1023.   (
  1024.     char *ps,
  1025.     char *en
  1026.   )
  1027. {
  1028. int ck;
  1029. char *p,c;
  1030.  
  1031.     ck = 0;
  1032.     p = ps;
  1033.     while (*p)                /* checksum the string */
  1034.         ck += *p++;
  1035.  
  1036.     c = ck;
  1037.  
  1038.     while (*en) {
  1039.         if ((((*ps ^ c) | 32) & 127) != *en)    /* XOR with checksum */
  1040.             return(0);
  1041.         if (*ps)
  1042.             ps++;
  1043.         else
  1044.             c++;            /* increment checksum to hide length */
  1045.         en++;
  1046.     }
  1047.  
  1048.     return(1);
  1049. }
  1050.  
  1051. /****************************************************************************/
  1052. /*  Scheckpass
  1053. *   Check the password file for the user,password combination
  1054. *   Returns valid or invalid
  1055. */
  1056. int Scheckpass
  1057.   (
  1058.     char *us,
  1059.     char *ps
  1060.   )
  1061. char *us,*ps;
  1062. {
  1063. char buf[81],*p;
  1064. FILE *fp;
  1065.  
  1066.     if (NULL == (fp = fopen(Scon.pass,"r"))) {
  1067.     
  1068. #ifdef MAC
  1069. /*
  1070. *  failed open, so try to find file in the system folder.
  1071. */
  1072.  
  1073.         sysdir();                            /* change to system folder */
  1074.         fp = fopen(Scon.pass,"r");
  1075.         
  1076.         setmydir();                            /* reset back to default dir */
  1077.         
  1078.         if (NULL == fp)                        /* still didn't work? */
  1079. #endif
  1080.             return(0);
  1081.     }
  1082.  
  1083.     while (NULL != fgets(buf,80,fp)) {
  1084.         p = strchr(buf,'\n');
  1085.         *p = '\0';                            /* remove \n */
  1086.  
  1087.         p = strchr(buf,':');                /* find delimiter */
  1088.         *p++ = '\0';
  1089.         if (!strcmp(buf,us) &&            /* found user */
  1090.             Scompass(ps,p)) {            /* does password check ?*/
  1091.             fclose(fp);
  1092.             return(1);
  1093.         }
  1094.     }
  1095.  
  1096.     fclose(fp);
  1097.     return(0);
  1098. }
  1099.  
  1100. /****************************************************************************/
  1101. /* Sneedpass
  1102. *  For other routines to call and find out if a password is required
  1103. */
  1104. int Sneedpass
  1105.   (
  1106.     void
  1107.   )
  1108. {
  1109.     if (Scon.pass == NULL)
  1110.         return(0);
  1111.  
  1112.     return(1);
  1113. }
  1114.  
  1115. /****************************************************************************/
  1116. /*  Sgetevent
  1117. *   gets events from the network and filters those for session related
  1118. *   activity.  Returns any other events to the caller.
  1119. */
  1120. int Sgetevent
  1121.   (
  1122.     int class,
  1123.     int *what,
  1124.     int *datp
  1125.   )
  1126. {
  1127. int retval;
  1128.  
  1129.     if (retval = netgetevent(SCLASS,what,datp)) {    /* session event */
  1130.         switch (retval) {
  1131.             case FTPACT:
  1132.                 ftpd(0,*datp);
  1133.                 break;
  1134. #ifdef PC
  1135.             case RCPACT:                /* give CPU to rsh for rcp */
  1136.                 rshd(0);
  1137.                 break;
  1138. #endif
  1139. #ifdef MAC
  1140.             case CLOSEDONE:                /* Used in the drivers */
  1141.                 netclose( *datp);
  1142.                 break;
  1143.             case CLOSEDONE+1:                /* Used in the drivers */
  1144.                 netclose( *datp);
  1145.                 break;
  1146. #endif MAC
  1147.             case UDPTO:                    /* name server not responding */
  1148.                 domto(*datp);
  1149.                 break;
  1150.             case RETRYCON:
  1151.                 if (0 < netopen2(*datp))     /* connection open yet? */
  1152.                     Stimerset(SCLASS,RETRYCON,*datp,4);  /* 4 is a kludge */
  1153.                 break;
  1154.  
  1155.             default:
  1156.                 break;
  1157.         }
  1158.     }
  1159.  
  1160.     Stask();                        /* allow net and timers to take place */
  1161.  
  1162.     if (!(retval = netgetevent(class,what,datp)))
  1163.         return(0);
  1164.         
  1165.     if (retval == CONOPEN) 
  1166.         Stimerunset(CONCLASS,CONFAIL,*datp);   /* kill this timer */
  1167.  
  1168.     if ((*datp == 997) && (retval == UDPDATA)) {
  1169.         udpdom();
  1170.     }
  1171.     else if ((*what == CONCLASS) && (Sptypes[*datp] >= 0)) {
  1172.                                         /* might be for session layer */
  1173.         switch (Sptypes[*datp]) {
  1174.             case PFTP:
  1175.                 rftpd(retval,*datp);        /* BYU 2.4.16 */
  1176.                 break;
  1177.             case PDATA:
  1178.                 ftpd(retval,*datp);
  1179.                 break;
  1180.             case UDATA:                        /* BYU */
  1181.                 userftpd(retval,*datp);        /* BYU */
  1182.                 break;                        /* BYU */
  1183. #ifdef PC
  1184.             case PRCP:
  1185.                 rshd(retval);
  1186.                 break;
  1187. #endif
  1188.             default:
  1189.                 break;
  1190.         }
  1191.     }
  1192.     else
  1193.         return(retval);                /* let higher layer have it */
  1194.  
  1195.     return(0);
  1196. }
  1197.  
  1198.  
  1199.